package org.xxpay.pay.ctrl.payment;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.xxpay.apibase.service.IDCNotifyService;
import org.xxpay.core.common.constant.MchConstant;
import org.xxpay.core.common.constant.PayConstant;
import org.xxpay.core.common.domain.api.ApiBuilder;
import org.xxpay.core.common.util.IPUtility;
import org.xxpay.core.common.util.MyLog;
import org.xxpay.core.common.util.XXPayUtil;
import org.xxpay.core.entity.MchAgentpayRecord;
import org.xxpay.core.entity.PayInterfaceType;
import org.xxpay.pay.channel.PayNotifyInterface;
import org.xxpay.pay.service.CommonService;
import org.xxpay.pay.service.LocalDynamicChannelService;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @Description: 接收支付渠道后端通知
 * @author dingzhiwei jmdhappy@126.com
 * @date 2017-03-02
 * @version V1.0
 * @Copyright: www.xxpay.vip
 */
@Controller
public class NotifyPayController {

	private static final MyLog _log = MyLog.getLog(NotifyPayController.class);

	@Autowired
    private CommonService commonService;

	@Autowired
	private LocalDynamicChannelService localDynamicChannelService;


	/**
	 * 支付渠道后台通知响应
	 * @param request
	 * @return
	 * @throws ServletException
	 * @throws IOException
     */
	@RequestMapping("/notify/{channel}/notify_res.htm")
	@ResponseBody
	public String payNotifyRes(HttpServletRequest request, HttpServletResponse response, @PathVariable("channel") String channel) throws Exception {
		_log.info("====== 开始接收{}支付回调通知 ======", channel);
        // 验证回调是否在白名单
        String notifyIp = IPUtility.getClientIp(request);
        String checkResult = notifyCheck(channel, notifyIp);
        if (checkResult != null) return checkResult;

		Object instance = localDynamicChannelService.getPayNotifyInterface(channel.toLowerCase());  //获取通道对象示例

		if(instance instanceof PayNotifyInterface){
			PayNotifyInterface payNotifyInterface = (PayNotifyInterface)instance;
			if(payNotifyInterface == null){
				return ApiBuilder.bizError("支付渠道类型[channel="+channel+"]实例化异常").toJSONString();
			}

			JSONObject retObj = payNotifyInterface.doNotify(request);
			String notifyRes = retObj.getString(PayConstant.RESPONSE_RESULT);
			_log.info("响应给{}:{}", channel, notifyRes);
			_log.info("====== 完成接收{}支付回调通知 ======", channel);
			return notifyRes;
		}


		//动态通道
		IDCNotifyService dcNotifyService = (IDCNotifyService)instance;
		dcNotifyService.doNotify(request, response);
		return null;

	}

	/**
	 * 支付渠道前台通知跳转
	 * @param request
	 * @return
	 * @throws ServletException
	 * @throws IOException
	 */
	@RequestMapping("/notify/{channel}/return_res.htm")
	public String payReturnRes(HttpServletRequest request, HttpServletResponse response, ModelMap model, @PathVariable("channel") String channel) throws Exception {
		_log.info("====== 开始接收{}支付前端同步跳转 ======", channel);

		Object instance = localDynamicChannelService.getPayNotifyInterface(channel.toLowerCase());  //获取通道对象示例

		if(instance instanceof PayNotifyInterface){
			PayNotifyInterface payNotifyInterface = (PayNotifyInterface)instance;
			if(payNotifyInterface == null){
				return ApiBuilder.bizError("支付渠道类型[channel="+channel+"]实例化异常").toJSONString();
			}

			JSONObject retObj = payNotifyInterface.doReturn(request);
			String notifyRes = retObj.getString(PayConstant.RESPONSE_RESULT);
			String jumpUrl = retObj.getString(PayConstant.JUMP_URL);
			_log.info("响应给{}:{}", channel, notifyRes);
			_log.info("====== 完成接收{}支付前端同步跳转 ======", channel);

			if(StringUtils.isNotBlank(jumpUrl)) {
				response.sendRedirect(jumpUrl);
				return null;
			}

			return "notify/show";


		}else{  //动态通道 自行处理

			IDCNotifyService dcNotifyService = (IDCNotifyService)instance;
			boolean isDefault = dcNotifyService.doReturn(request, response);
			if(isDefault){
				return "notify/show";
			}
			return null;
		}
	}

	/**
	 * 验证回调IP是否白名单
	 * @param channel
	 * @param notifyIp
	 * @return 返回null程序继续执行回调,返回字符串回调停止
	 */
    private String notifyCheck(String channel, String notifyIp) {
		_log.info("通道:{},回调IP:{}", channel, notifyIp);
        PayInterfaceType interfaceType = commonService.payInterfaceTypeService.findByCode(channel);
        if(interfaceType == null) {
			_log.warn("通道:{},不存在", channel);
        	return "通道[" + channel + "]不存在";
		}

        // 是否开启异步回调
        Byte enableNotify = interfaceType.getEnableNotify();
        if(enableNotify != MchConstant.PUB_YES) {
			_log.warn("通道:{},不允许回调", channel);
			return "通道已关闭回调";
		}

        // 校验白名单
        String whiteIp = interfaceType.getWhiteIp();
        // 没有配置白名单,继续执行回调
        if (StringUtils.isEmpty(whiteIp)) return null;

		Boolean result = XXPayUtil.ipAllow4Strong(notifyIp, whiteIp, null);
        if(result) return null;

		_log.info("通道:{},IP不在白名单,禁止访问.回调IP={},白名单IP={}", channel, notifyIp, whiteIp);
		return "ip [" + notifyIp + "] 不在白名单";

    }


}
